Skip to content

security(hooks): fix the two critical v0.22.1 re-audit findings (CR-01, CR-02) + honest positioning (ME-24)#85

Merged
CodeWithJuber merged 1 commit into
masterfrom
claude/parallel-solving-3dc0ji
Jul 19, 2026
Merged

security(hooks): fix the two critical v0.22.1 re-audit findings (CR-01, CR-02) + honest positioning (ME-24)#85
CodeWithJuber merged 1 commit into
masterfrom
claude/parallel-solving-3dc0ji

Conversation

@CodeWithJuber

Copy link
Copy Markdown
Owner

What & why

The v0.22.1 edge-case re-audit found two critical defects in the secret-redaction guard, plus remaining enforcement overclaims in the docs. This PR fixes exactly that scope.

CR-01 — PostToolUse redaction violated the structured-output contract. Built-in tools (Bash, Read, Grep, …) return structured objects, and Claude Code ignores an updatedToolOutput whose shape doesn't match the original — the redactor stringified objects, so its replacement was silently discarded and the unredacted, secret-bearing output stayed visible. The redactor now redacts recursively while preserving the value's exact structure: strings redacted in place, arrays/objects keep their keys, non-string leaves (numbers, booleans, null) pass through untouched, and an unchanged response emits no rewrite at all.

CR-02 — strict mode was a false promise, twice. (a) The shell wrapper ran node "$MJS" then unconditionally exit 0, erasing the strict-mode exit 2 before Claude ever saw it — it now propagates the child's exit status. (b) Comments and docs claimed FORGE_GUARD_STRICT=1 "makes degradation blocking" — PostToolUse fires after the tool already ran and cannot block; all wording now states exit 2 is surfaced stderr feedback, with blocking belonging to the PreToolUse guard.

ME-24 — honest positioning. README no longer claims "one brain for every AI coding agent", "enforced guardrails", or "every task passes a fast, deterministic gate"; automatic hooks are described as Claude Code-specific and advisory by default (enforcement opt-in via FORGE_ENFORCE=1), and guardrails as defence in depth, not a security sandbox. The GUIDE's FORGE_GUARD_STRICT row states the visibility-not-blocking semantics.

Checklist

  • npm test passes (984 tests, 0 fail — 5 new: Bash-shaped object, Grep-shaped nested response, clean-object no-op, and two wrapper-level strict-mode tests driving the real secret-redact.sh)
  • npm run check passes (Biome)
  • New public functions have a test (redactValue covered via the guard's structured-response tests)
  • Conventional commit message (security:)
  • CHANGELOG.md updated under ## [Unreleased]
  • No new runtime dependency
  • Substrate/docs updated (GUIDE env-var table; forge docs check green)

Risk & rollback

  • Risk level: low — the redactor's output for plain-string responses is byte-identical to before; the only behavioral changes are correct object-shaped replacements, a propagated exit status, and doc wording.
  • Rollback plan: revert the single commit.

Extra checks (tick if applicable)

  • npm run typecheck passes
  • Input validated at boundaries; errors handled (degradation stays loud; no swallowing)
  • Logs contain no secrets/PII (test literals built via test/_fixtures.js helpers)
  • If AI-assisted: I understand it, verified the package APIs, and it has tests

🤖 Generated with Claude Code

https://claude.ai/code/session_01KfCEnSJzSG914yyVesjjD6


Generated by Claude Code

…t mode; qualified enforcement claims (CR-01, CR-02, ME-24)

- secret-redact.mjs redacts recursively while preserving the tool_response's
  exact structure, so Claude Code no longer discards the replacement for
  structured built-in outputs and keeps the unredacted original.
- secret-redact.sh propagates the redactor's exit status instead of an
  unconditional exit 0, so FORGE_GUARD_STRICT=1 degradation (exit 2) actually
  reaches Claude. Comments/docs now state PostToolUse cannot block — exit 2
  is surfaced stderr feedback; blocking belongs to the PreToolUse guard.
- Tests: Bash/Grep-shaped structured responses keep object shape, clean
  structured response emits nothing, wrapper-level strict tests drive the
  real secret-redact.sh.
- README/GUIDE wording: hooks are Claude Code-specific and advisory by
  default; guardrails are defence in depth, not a sandbox.

Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01KfCEnSJzSG914yyVesjjD6
@CodeWithJuber
CodeWithJuber marked this pull request as ready for review July 19, 2026 05:38
@CodeWithJuber
CodeWithJuber merged commit 6ccc6c5 into master Jul 19, 2026
9 checks passed
@mintlify

mintlify Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Docs PR opened: #86

Added a July 19 changelog entry covering the secret-redactor structured-output fix, strict-mode exit propagation, and clearer hook positioning.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants